package com.shang.core.base;

import java.nio.charset.Charset;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Created by shangwei2009@hotmail.com on 2021/9/24 10:35
 */
public abstract class AbstractBitMap extends Value {

    private static final Pattern BINARY = Pattern.compile("^[01]+$");

    protected AbstractBitMap(Meta meta, Charset charset, PadPosition padPosition, String paddingHex) {
        super(meta, charset, padPosition, paddingHex);
    }

    @Override
    protected void decodeChildren(String hexStr, String plainStr, String rightHexStr, List<Value> from, List<Wrapper> to) {
        if (!BINARY.matcher(plainStr).matches()) {
            throw new CodecException(getFieldName() + "只能解析为二进制数字符串");
        }
        if (plainStr.length() != 64 && plainStr.length() != 128) {
            throw new CodecException(getFieldName() + "只能为64bit或128bit二进制数");
        }
        if (plainStr.length() == 64 && !plainStr.startsWith("0")) {
            throw new CodecException(getFieldName() + "为64bit时只能以0开头");
        }
        if (plainStr.length() == 128 && !plainStr.startsWith("1")) {
            throw new CodecException(getFieldName() + "为128bit时只能以1开头");
        }
        if (plainStr.length() == 128 && plainStr.charAt(64) != '0') {
            throw new CodecException(getFieldName() + "为128bit时第65域对应标记必须为0（65域不存在）");
        }
        // 域可多，但不可少
        if (plainStr.length() > from.size()) {
            throw new CodecException(getFieldName() + "应当配置" + plainStr.length() + "个域编解码器");
        }
        final String[] flags = plainStr.split("");
        Wrapper wrapper = new Wrapper(0, "", "", rightHexStr);
        for (int i = 0; i < flags.length; i++) {
            final Value child = from.get(i);
            if (child instanceof AbstractBitMap) {
                throw new CodecException((i + 1) + "域不能继承AbstractBitMap");
            }
            if ("1".equals(flags[i])) {
                if (i == 0) {
                    // 有扩展位图
                    to.add(child.decode(hexStr.substring(hexStr.length() / 2)));
                } else {
                    wrapper = child.decode(wrapper.getRightHexStr());
                    to.add(wrapper);
                }
            }
        }
    }
}
